package edu.ustb.efws.pipeline.collect.handler;

import edu.ustb.efws.base.domain.Position;
import edu.ustb.efws.pipeline.domain.RiskLog;
import edu.ustb.efws.pipeline.service.RiskLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 实现监控点风险值处理
 *
 * @author TS Group
 */
abstract class RiskLogHandler<T> implements PipelineHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(RiskLogHandler.class);

    private final Map<Integer, Position> monitorPositions;
    private final RiskLogService riskLogService;

    /**
     * 构造{@link RiskLogHandler}
     *
     * @param positions 监测点集合
     * @param riskLogService {@link RiskLogService}
     */
    RiskLogHandler(List<Position> positions, RiskLogService riskLogService) {

        this.monitorPositions = filterMonitorPositions(positions);
        this.riskLogService = riskLogService;
    }

    /**
     * 过滤监控点方法
     *
     * @param positions 监控点集合
     * @return 需要监控点
     */
    protected abstract Map<Integer, Position> filterMonitorPositions(List<Position> positions);

    @Override
    @SuppressWarnings("unchecked")
    public Optional<Object> handle0(Object data) {
        List<T> logs = (List<T>)data;
        if(logs == null || logs.isEmpty()){
            return Optional.empty();
        }

        Position position = getPosition(monitorPositions, logs.get(0));
        if(position == null){
            return Optional.empty();
        }

        if(!isDetectorActive(position)){
            LOGGER.warn("Risk detector not active positionId={}, posId={}, thoId={}",
                    position.getId(), position.getIptId(), position.getThoId());
            return Optional.empty();
        }

        List<RiskLog> riskLogs = logs.stream()
                .map(e -> buildLog(position, e))
                .collect(Collectors.toList());

        riskLogService.save(riskLogs);

        return Optional.of(riskLogs);
    }

    /**
     * 获取{@link Position}
     *
     * @param t T
     * @return {@link Position}
     */
    protected abstract Position getPosition(Map<Integer, Position> monitorPositions, T t);

    /**
     * 设备数据采集是否正常
     *
     * @param position {@link Position}
     * @return true 激活
     */
    protected abstract boolean isDetectorActive(Position position);

    /**
     * 构建风险日志
     *
     * @param position {@link Position}
     * @param t T
     * @return {@link RiskLog}
     */
    protected abstract RiskLog buildLog(Position position, T t);

}
